﻿using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using SelfService.Model.Models;
using SelfService.ViewModel.SysClientVMs;
using TT;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;
using WalkingTec.Mvvm.Mvc.Auth;

namespace SelfService.Helpers
{
    public static class CommonExtension
    {
        /// <summary>
        /// 获取客户端配置信息
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public static async Task<SysClientVm> GetClientAsync(this BaseApiController controller)
        {
            var ip = controller.HttpContext.Connection.RemoteIpAddress?.ToString().Replace(":", "").Replace("f", "");
            #if DEBUG
                ip = "127.0.0.1";
            #endif
            if (string.IsNullOrWhiteSpace(ip)) return null;
            var client = await controller.DC.Set<SysClient>().FirstOrDefaultAsync(e => e.Ip == ip);
            if (client == null) return null;
            client.LastTime = DateTime.Now;
            await controller.DC.SaveChangesAsync();
            var vm = controller.Wtm.CreateVM<SysClientVm>(client.ID.ToString());
            LoginUserInfo user = new LoginUserInfo
            {
                ITCode = vm.Entity.User.ITCode,
                UserId = vm.Entity.User.ID.ToString()
            };
            await user.LoadBasicInfoAsync(controller.Wtm);
            controller.Wtm.LoginUserInfo = user;
            if (controller.HttpContext.RequestServices.GetService(typeof(ITokenService)) is ITokenService authService)
            {
                var token = await authService.IssueTokenAsync(controller.Wtm.LoginUserInfo);
                vm.Token = $"{token.TokenType} {token.AccessToken}";
            }
            return vm;
        }

        /// <summary>
        /// 返回JSON数据
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static ContentResult Json(this BaseApiController controller, object data)
        {
            return controller.Content(System.Text.Json.JsonSerializer.Serialize(data), "application/json");
        }

        /// <summary>
        /// 记录患者行为
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="cardNo"></param>
        /// <param name="action"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public static async Task<Result<SysPatient>> CheckPatient(this BaseApiController controller, string cardNo, string action, decimal amount = 0)
        {
            var patient = await controller.DC.Set<SysPatient>().FirstOrDefaultAsync(e => e.CardNo == cardNo);
            if (patient == null)
            {
                return new Result<SysPatient>()
                {
                    Code = 1,
                    Message = "用户尚未建档"
                };
            }
            var patientLog = new SysPatientLog();
            patientLog.ID = Guid.NewGuid();
            patientLog.Action = action;
            patientLog.CreateTime = DateTime.Now;
            patientLog.PatientId = patient.ID;
            await controller.DC.Set<SysPatientLog>().AddAsync(patientLog);
            await controller.DC.SaveChangesAsync();
            return new Result<SysPatient>()
            {
                Data = patient
            };
        }

        /// <summary>
        /// 记录患者行为
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="patientId"></param>
        /// <param name="action"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public static async Task<Result<SysPatient>> CheckPatient(this BaseApiController controller, Guid? patientId, string action, decimal amount = 0)
        {
            var patient = await controller.DC.Set<SysPatient>().FirstOrDefaultAsync(e => e.ID == patientId);
            if (patient == null)
            {
                return new Result<SysPatient>()
                {
                    Code = 1,
                    Message = "用户尚未建档"
                };
            }
            var patientLog = new SysPatientLog();
            patientLog.ID = Guid.NewGuid();
            patientLog.Action = action;
            patientLog.CreateTime = DateTime.Now;
            patientLog.PatientId = patient.ID;
            await controller.DC.Set<SysPatientLog>().AddAsync(patientLog);
            await controller.DC.SaveChangesAsync();
            return new Result<SysPatient>()
            {
                Data = patient
            };
        }

        /// <summary>
        /// 记录日志
        /// </summary>
        /// <param name="base"></param>
        /// <param name="message"></param>
        /// <param name="type"></param>
        public static void Logger(this BaseApiController @base, string message, ActionLogTypesEnum type = ActionLogTypesEnum.Normal)
        {
            @base.Wtm.DoLog(
                message, 
                type, 
                @base.RouteData?.Values["controller"]?.ToString(), 
                @base.RouteData?.Values["action"]?.ToString(),
                @base.HttpContext?.Connection?.RemoteIpAddress?.ToString().Replace(":", ""), 
                @base.HttpContext?.Request?.GetDisplayUrl());
            var scope = @base.Wtm.ServiceProvider.CreateScope();
            var logger = scope.ServiceProvider.GetRequiredService<Logger>();
            switch (type)
            {
                case ActionLogTypesEnum.Normal:
                case ActionLogTypesEnum.Job:
                    logger.Info(message, $"{@base.RouteData?.Values["controller"]},{@base.RouteData?.Values["action"]}");
                    break;
                case ActionLogTypesEnum.Exception:
                    logger.Error(message, $"{@base.RouteData?.Values["controller"]},{@base.RouteData?.Values["action"]}");
                    break;
                case ActionLogTypesEnum.Debug:
                    logger.Debug(message, $"{@base.RouteData?.Values["controller"]},{@base.RouteData?.Values["action"]}");
                    break;
            }
        }
    }
}